#ifndef __LIST_H
#define __LIST_H


#include "./portmacro.h"

/*
*************************************************************************
*                               类型定义
*************************************************************************
*/

struct xLIST_ITEM
{
	TickType_t xItemValue;                    /* 辅助值, 用于帮助节点做顺序排列, 凡是涉及到数据类型的地方, 都会将标准的 C 数据类型用 typedef 重新取一个别名 
																							 且 放在 portmacro.h 中*/
	struct xLIST_ITEM *pxNext;                /* 指向链表的下一个节点 */
	struct xLIST_ITEM *pxPrevious;            /* 指向链表前一个节点 */
	void * pvOwner;                           /* 指向拥有该节点的内核对象, 通常是 TCB */
	void * pvContainer;                       /* 指向该节点所在的链表 */
};

typedef struct xLIST_ITEM ListItem_t;       /* 节点数据类型定义 */


/* 精简节点：生产者, 相比于列表项少了 pvOwner 和 pvContainer 两个成员*/
struct xMINI_LIST_ITEM
{
	TickType_t xItemValue;                    /* 辅助值, 用于帮助节点做顺序排列, 凡是涉及到数据类型的地方, 都会将标准的 C 数据类型用 typedef 重新取一个别名
																							 且 放在 portmacro.h 中*/
	struct xLIST_ITEM *pxNext;								/* 指向链表的下一个节点 */
	struct xLIST_ITEM *pxPrevious;            /* 指向链表前一个节点 */
};                                          

typedef struct xMINI_LIST_ITEM MiniListItem_t;


/* 根节点数据结构 */
typedef struct xLIST
{
	UBaseType_t      uxNumberOfItems;         /* 链表节点计数器   : 用于表示链表下有多少个节点, 除根节点外 */
	ListItem_t       *pxIndex;                /* 链表节点索引指针 : 节点索引指针, 用于遍历节点, 指向的位置在运行过程当中会发生变化 */
	MiniListItem_t   xListEnd;                /* 链表最后一个节点 : 链表最后一个节点, 实际也是链表的第一个节点 */
}List_t;


/*
*************************************************************************
*                               宏函数
*************************************************************************
*/

/* 初始化节点的拥有者 */
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) \
				( ( pxListItem )->pvOwner = ( void * ) (pxOwner) )

/* 获取节点拥有者 */
#define listGET_LIST_ITEM_OWNER( pxListItem ) \
				( ( pxListItem )->pvOwner )

/* 获取节点排序辅助值 */
#define listGET_LIST_ITEM_VALUE( pxListItem ) \
				( ( pxListItem )->xItemValue )

/* 获取根节点的节点计数器值 */
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY ( pxList ) \
				( ( ( pxList )->xListEnd ).pxNext->xItemValue )
				
/* 获取链表的头节点, 即 end 节点的 next */
#define listGET_HEAD_ENTRY ( pxList ) \
				( ( ( pxList )->xListEnd ).pxNext )
				
/* 获取节点的 next 节点 */
#define listGET_NEXT( pxListItem ) \
				( ( pxListItem)->pxNext )
				
/* 获取链表的最后一个节点 */
#define listGET_END_MARKER( pxList ) \
				( ( ListItem_t const * ) ( & ( (pxList)->xListEnd ))) 

/* 判断链表是否为空 */
#define listLIST_IS_EMPTY( pxList ) \
				((BaseType_t) ( ( pxList )->uxNumberOfItems == (UBaseType_t)0 ) )

/* 获取链表的节点数 */
#define listCURRENT_LIST_LENGTH( pxList ) \
				( ( pxList )->uxNumberOfItems )
				
/* 获取节点下一个节点的 owner */
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) 																		\
{                                                                                       \
	List_t * const pxConstList = ( pxList );																							\
	                                                                                      \
	/* 节点索引指向链表第一个节点: 任务是在这里切换, 实现时间片的关键代码 */              \
	( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                          \
	                                                                                      \
	/* 若下一个节点是 end 节点, 则更新 pxIndex 为 end 的next.  */                         \
	/* 注意: 链表的 pxIndex 发生移动 */                                                   \
	/* TODO: 虽然外部调用限制了不能空表调用, 但是健壮性可以再提高点*/                     \
	if( (void *) ( pxConstList )->pxIndex == (void *) &(( pxConstList )->xListEnd ) )     \
	{                                                                                     \
		( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;                        \
	}                                                                                     \
	                                                                                      \
	/* 获取节点的OWNER, 即 TCB */                                                         \
	( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;                                        \
}

/* 获取链表的第一个节点的owner */
#define listGET_OWNER_OF_HEAD_ENTRY( pxList )  ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )

/* 设置节点的排序辅助值 */
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue )	( ( pxListItem )->xItemValue = ( xValue ) )

/*
*************************************************************************
*                               函数声明
*************************************************************************
*/
extern void vListInitialise(List_t * const pxList);
extern void vListInitialiseItem(ListItem_t * const pxItem);
extern UBaseType_t uxListRemove(ListItem_t * const pxItemToRemove);
extern void vListInsert(List_t * const pxList, ListItem_t * const pxNewListItem);
extern void vListInsertEnd(List_t * const pxList, ListItem_t * const pxNewListItem);

#endif
